package com.milloc.db.service.impl;

import com.milloc.db.dto.PageDTO;
import com.milloc.db.dto.PageOutDTO;
import com.milloc.db.dto.SQLEntityDTO;
import com.milloc.db.entity.DataSourceEntity;
import com.milloc.db.entity.SQLEntity;
import com.milloc.db.repository.SQLEntityRepository;
import com.milloc.db.service.SQLRunnerService;
import com.milloc.db.service.SQLService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.Join;
import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import static com.milloc.db.util.SQLUtils.like;

/**
 * @author gongdeming
 * @create 2019-08-27
 */
@Service
public class SQLServiceImpl implements SQLService {
    private final SQLEntityRepository aSQLEntityRepository;
    private final SQLRunnerService aSQLRunnerService;

    public SQLServiceImpl(SQLEntityRepository aSQLEntityRepository, SQLRunnerService aSQLRunnerService) {
        this.aSQLEntityRepository = aSQLEntityRepository;
        this.aSQLRunnerService = aSQLRunnerService;
    }

    @Override
    public SQLEntity save(SQLEntity aSQLEntity) {
        if (aSQLEntity.getId() != null) {
            aSQLRunnerService.reloadSQL(aSQLEntity.getId());
        }
        return aSQLEntityRepository.saveAndFlush(aSQLEntity);
    }

    @Override
    public void remove(String aSQLEntityId) {
        aSQLRunnerService.reloadSQL(aSQLEntityId);
        aSQLEntityRepository.deleteById(aSQLEntityId);
    }

    @Override
    public SQLEntity fetchOne(String aSQLEntityId) {
        return aSQLEntityRepository.getOne(aSQLEntityId);
    }

    @Override
    public PageOutDTO<SQLEntity> listAll(SQLEntityDTO aSQLEntityDTO, PageDTO pageDTO) {
        Page<SQLEntity> res = aSQLEntityRepository.findAll((root, query, builder) -> {
            Join<SQLEntity, DataSourceEntity> dataSourceEntity = root.join("dataSourceEntity");

            List<Predicate> predicates = new ArrayList<>();
            if (aSQLEntityDTO.getSQLEntityId() != null) {
                predicates.add(builder.equal(root.get("id"), aSQLEntityDTO.getSQLEntityId()));
            }

            if (aSQLEntityDTO.getPage() != null) {
                predicates.add(builder.equal(root.get("page"), aSQLEntityDTO.getPage()));
            }

            if (StringUtils.isNotBlank(aSQLEntityDTO.getKeyword())) {
                String keyword = like(aSQLEntityDTO.getKeyword());
                Predicate nameLike = builder.like(root.get("name"), keyword);
                Predicate descriptionLike = builder.like(root.get("description"), keyword);
                Predicate dataSourceLike = builder.like(dataSourceEntity.get("name"), keyword);
                predicates.add(builder.or(nameLike, descriptionLike, dataSourceLike));
            }
            return builder.and(predicates.toArray(new Predicate[]{}));
        }, pageDTO.pageRequest());

        return PageOutDTO.from(res);
    }
}
